package com.ruoyi.coin.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.ruoyi.coin.enums.OklinkChainEnum;
import com.ruoyi.coin.enums.OklinkTranFlagEnum;
import com.ruoyi.coin.model.ave.AvePhoneHotTokenModel;
import com.ruoyi.coin.model.ave.AveTokenModel;
import com.ruoyi.coin.service.ICoinBaseSqlService;
import com.ruoyi.coin.service.ICoinService;
import com.ruoyi.coin.utils.BuySellUtils;
import com.ruoyi.coin.utils.CoinUtils;
import com.ruoyi.coin.utils.ave.AvueUtils;
import com.ruoyi.coin.utils.oklink.OklinkUtils;
import com.ruoyi.common.config.CoinConfig;
import com.ruoyi.common.utils.MjkjUtils;
import com.ruoyi.common.utils.blade.Func;
import com.ruoyi.common.utils.blade.tool.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 币种信息
 */
@Slf4j
@Service
public class CoinServiceImpl implements ICoinService {

    @Autowired
    private ICoinBaseSqlService baseSqlService;

    /**
     * 同步手机端热门列表
     */
    @Override
    public void buyToken(){
        //获取热门
        List<AvePhoneHotTokenModel> hotTokenModelList = AvueUtils.getPhoneIndexHotList();
        if(Func.isEmpty(hotTokenModelList)){
            return;
        }
        for(AvePhoneHotTokenModel hotTokenModel:hotTokenModelList){
            try{
                if( CoinUtils.blackTokenlist.contains(hotTokenModel.getToken())){
                    continue;
                }
                Integer holders = hotTokenModel.getHolders();
                if(holders<300){
                    continue;
                }

                String chain = hotTokenModel.getChain();
                OklinkChainEnum oklinkChainEnum = OklinkChainEnum.getByCode(chain);
                String tokenAddress = hotTokenModel.getToken();


                QueryWrapper wrapper = MjkjUtils.getQueryWrapper();
                wrapper.eq("chain_type", chain);
                wrapper.eq("token_address", tokenAddress);//合约地址
                //查询token是否存在
                List<Map<String, Object>> tokenList = baseSqlService.getDataListByWrapper("coin_token",wrapper);
                if(Func.isEmpty(tokenList)){//合约
                    AveTokenModel.Tokenodel tokenInfo = AvueUtils.getAveTokenInfo(oklinkChainEnum, tokenAddress);
                    if(Func.isEmpty(tokenInfo)){
                        continue;
                    }

                    //新增入库
                    long tokenId = IdWorker.getId();
                    Map<String, Object> tokenMap = new HashMap<>();
                    tokenMap.put("chain_type", chain);
                    tokenMap.put("symbol", tokenInfo.getSymbol());
                    tokenMap.put("token_address", tokenAddress);
                    tokenMap.put("accuracy", tokenInfo.getDecimal());
                    tokenMap.put("logo_url", tokenInfo.getLogo_url());
                    tokenMap.put("holders", tokenInfo.getHolders());
                    tokenMap.put("risk_level", tokenInfo.getRisk_level());
                    tokenMap.put("risk_score", tokenInfo.getRisk_score());
                    tokenMap.put("id", tokenId);
                    baseSqlService.baseInsertData("coin_token", tokenMap);

                }else{//已存在
                    Map<String, Object> tokenInfoMap = tokenList.get(0);
                    Long id = MjkjUtils.getMap2Long(tokenInfoMap, "id");
                    String isBuy = MjkjUtils.getMap2Str(tokenInfoMap, "is_buy");
                    String dynamicTag = MjkjUtils.getMap2Str(tokenInfoMap, "dynamic_tag");
                    if(Func.isNotEmpty(dynamicTag)){
                        continue;
                    }
                    if(Func.equals(isBuy,"Y")){//已经卖出了
                        continue;
                    }
                }


                //新增完成，进行交易
                buyToken(oklinkChainEnum,tokenAddress);//热门8小时内

            }catch (Exception e){
                e.printStackTrace();
            }
        }

    }


    /**
     * 购买币种
     */
    @Override
    public void buyToken( OklinkChainEnum oklinkChainEnum,String tokenAddress) {
        //获取
        Map<String, Object> tokenMap = baseSqlService.getDataOneByField("coin_token", "token_address", tokenAddress);
        if(Func.isEmpty(tokenMap)){
            return;
        }
        Long tokenId = MjkjUtils.getMap2Long(tokenMap, "id");

        //判断是否有购买果
        List<Map<String, Object>> tranMapList = baseSqlService.getDataListByField("coin_log_transaction", "token_address", tokenAddress);
        if(Func.isNotEmpty(tranMapList)){//已经购买过了
            return;
        }


        AveTokenModel.Tokenodel tokenInfo = AvueUtils.getAveTokenInfo(oklinkChainEnum, tokenAddress);
        if(Func.isEmpty(tokenInfo)){
            return;
        }
        //K线小时数
        Integer hourKlineCou = AvueUtils.get1HourKlineCou(oklinkChainEnum, tokenInfo.getMain_pair());
        if(hourKlineCou==-1 || hourKlineCou>oklinkChainEnum.getKiline()){//大于8小时(主要)
            CoinUtils.blackTokenlist.add(tokenAddress);//加入黑名单

            Map<String,Object> updateTokenMap=new HashMap<>();
            updateTokenMap.put("dynamic_tag","K线过多");
            baseSqlService.baseUpdateDataLong("coin_token",updateTokenMap,tokenId);

            return;
        }

        try {
            String hash = BuySellUtils.buyToken(oklinkChainEnum,  tokenAddress,tokenInfo.getDecimal());

            BigDecimal buyPrice = AvueUtils.getNewPrice(oklinkChainEnum, tokenInfo.getMain_pair());

            Thread.sleep(5000L);
            Boolean tranFlag =false;
            String tran_state=null;
            if (Func.isNotEmpty(hash)) {
                tranFlag=true;

                OklinkTranFlagEnum oklinkTranFlagEnum = OklinkUtils.getTranFlagByHash(oklinkChainEnum, hash);
                if(Func.isNotEmpty(oklinkTranFlagEnum)){
                    if(Func.equals(OklinkTranFlagEnum.SUCCESS,oklinkTranFlagEnum)){
                        tran_state="Y";
                    }else if(Func.equals(OklinkTranFlagEnum.FAIL,oklinkTranFlagEnum)){
                        tran_state="N";
                    }
                }
            }






            if (tranFlag) {//更新主表
                Map<String, Object> updateTokenMap = new HashMap<>();
                updateTokenMap.put("is_buy", "Y");
                baseSqlService.baseUpdateDataLong("coin_token", updateTokenMap, tokenId);
            }

            Date tranTime = DateUtil.now();
            //插入交易记录
            Map<String, Object> tranMap = new HashMap<>();
            tranMap.put("symbol",tokenInfo.getSymbol());
            tranMap.put("buy_price",buyPrice);//购买价格
            tranMap.put("chain_type", oklinkChainEnum.getCode());//链路类型
            tranMap.put("token_address", tokenAddress);//合约地址
            tranMap.put("user_address", CoinConfig.getWallet_address());//用户地址
            tranMap.put("good_wallet_cou",-99);

            tranMap.put("token_id", tokenId);
            tranMap.put("hash", hash);
            tranMap.put("tran_type", "BUY");//买入
            tranMap.put("tran_time", tranTime);
            tranMap.put("tran_state", tran_state);//交易状态
            tranMap.put("is_sell", "N");//未卖出
            tranMap.put("sell_scale",oklinkChainEnum.getSellRatio());//卖出比例
            baseSqlService.baseInsertData("coin_log_transaction", tranMap);

            System.out.println("购买成功："+JSONUtil.toJsonStr(tranMap));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 出售币种
     */
    public void sellToken() {
        //查询所有买入，未卖出的币种
        QueryWrapper wrapper = MjkjUtils.getQueryWrapper();
        wrapper.eq("is_sell", "N");//未卖出
        wrapper.eq("tran_type", "BUY");//买入
        wrapper.eq("tran_state", "Y");//购买成功
        List<Map<String, Object>> tranMapList = baseSqlService.getDataListByWrapper("coin_log_transaction", wrapper);
        if (Func.isEmpty(tranMapList)) {
            return;
        }

        for (Map<String, Object> tranMap : tranMapList) {
            try {
                Long id = MjkjUtils.getMap2Long(tranMap, "id");
                Long tokenId = MjkjUtils.getMap2Long(tranMap, "token_id");
                String symbol = MjkjUtils.getMap2Str(tranMap, "symbol");
                String chainType = MjkjUtils.getMap2Str(tranMap, "chain_type");
                String tokenAddress = MjkjUtils.getMap2Str(tranMap, "token_address");
                String userAddress = MjkjUtils.getMap2Str(tranMap, "user_address");
                BigDecimal buyPrice = MjkjUtils.getMap2BigD(tranMap, "buy_price");
                BigDecimal sellScale = MjkjUtils.getMap2BigD(tranMap, "sell_scale");//卖出比例
                OklinkChainEnum oklinkChainEnum = OklinkChainEnum.getByCode(chainType);

                if(sellScale.compareTo(BigDecimal.ZERO)!=1){
                    continue;
                }


                //查询是否有卖出记录
                QueryWrapper sellWrapper = MjkjUtils.getQueryWrapper();
                sellWrapper.eq("chain_type",chainType);
                sellWrapper.eq("tran_type","SELL");
                sellWrapper.eq("token_id",tokenId);
                List<Map<String, Object>> sellMapList = baseSqlService.getDataListByWrapper("coin_log_transaction", sellWrapper);
                if(Func.isNotEmpty(sellMapList)){
                    continue;
                }

                //5分钟外，
                AveTokenModel.Tokenodel tokenInfo = AvueUtils.getAveTokenInfo(oklinkChainEnum, tokenAddress);
                if (Func.isEmpty(tokenInfo)) {//获取币种失败
                    continue;
                }

                BigDecimal nowPrice = AvueUtils.getNewPrice(oklinkChainEnum, tokenInfo.getMain_pair());
                if(nowPrice.compareTo(BigDecimal.ZERO)!=1){
                    continue;
                }
                //利润
                buyPrice=buyPrice.multiply(sellScale);

                if(nowPrice.compareTo(buyPrice)!=1){//必须要当前价格 > 买入价格
                    continue;
                }

                try {
                    //链上购买
                    String hash = BuySellUtils.sellToken(oklinkChainEnum, tokenAddress,tokenInfo.getDecimal());

                    Thread.sleep(5000L);
                    Boolean tranFlag =false;
                    String tran_state=null;
                    if (Func.isNotEmpty(hash)) {
                        tranFlag=true;

                        OklinkTranFlagEnum oklinkTranFlagEnum = OklinkUtils.getTranFlagByHash(oklinkChainEnum, hash);
                        if(Func.isNotEmpty(oklinkTranFlagEnum)){
                            if(Func.equals(OklinkTranFlagEnum.SUCCESS,oklinkTranFlagEnum)){
                                tran_state="Y";
                            }else if(Func.equals(OklinkTranFlagEnum.FAIL,oklinkTranFlagEnum)){
                                tran_state="N";
                            }
                        }
                    }


                    if(tranFlag){
                        //更新主表
                        Map<String, Object> updateTokenMap = new HashMap<>();
                        updateTokenMap.put("is_sell", "Y");//已出售
                        baseSqlService.baseUpdateDataLong("coin_token", updateTokenMap, tokenId);

                        //更新为已出售
                        Map<String, Object> updateMap = new HashMap<>();
                        updateMap.put("is_sell", "Y");
                        baseSqlService.baseUpdateDataLong("coin_log_transaction", updateMap, id);
                    }

                    Date sellTime = DateUtil.now();
                    //插入交易记录
                    Map<String, Object> sellMap = new HashMap<>();
                    sellMap.put("chain_type", chainType);//链路类型
                    sellMap.put("symbol",symbol);
                    sellMap.put("buy_price",nowPrice);//卖出价格
                    sellMap.put("token_address", tokenAddress);//合约地址
                    sellMap.put("user_address", CoinConfig.getWallet_address());//用户地址
                    sellMap.put("good_wallet_cou",0);

                    sellMap.put("token_id", tokenId);
                    sellMap.put("hash", hash);
                    sellMap.put("tran_type", "SELL");//买入
                    sellMap.put("tran_time", sellTime);
                    sellMap.put("tran_state", tran_state);//交易状态
                    sellMap.put("is_sell", tran_state);//未卖出
                    sellMap.put("sell_scale",oklinkChainEnum.getSellRatio());//卖出比例
                    baseSqlService.baseInsertData("coin_log_transaction", sellMap);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }


}
